package dev.ahamed.mva.sample.slice;

import dev.ahamed.mva.sample.ResourceTable;
import dev.ahamed.mva.sample.data.model.NumberItem;
import dev.ahamed.mva.sample.util.Utils;
import dev.ahamed.mva.sample.view.basic.BasicItemModel;
import dev.ahamed.mva.sample.view.widget.DistanceModel;
import dev.ahamed.mva.sample.view.widget.HintModel;
import mva2.adapter.ultimateprovider.Model;
import mva2.adapter.ultimateprovider.UltimateProvider;
import ohos.aafwk.content.Intent;
import ohos.agp.animation.AnimatorProperty;
import ohos.agp.components.*;
import ohos.eventhandler.EventHandler;
import ohos.eventhandler.EventRunner;
import ohos.eventhandler.InnerEvent;
import ohos.multimodalinput.event.TouchEvent;

import java.util.ArrayList;
import java.util.List;

/**
 * BasicAbilitySlice
 *
 * @since 2021.07.08
 */
public class BasicAbilitySlice extends AbsAbilitySlice {
    private static final int LAYOUTMANAGER_LINEAR = 1;
    private static final int LAYOUTMANAGER_GRID = 2;
    private static final String LINEAR = "Linear";
    private static final String GRID = "Grid";
    private static final String VERTICAL = "Vertical";
    private static final String HORIZONTAL = "Horizontal";
    private static final int SHOW_MENU_LAYOUTMANAGER = 1000;
    private static final int HIDE_MENU_LAYOUTMANAGER = 1001;
    private static final int SHOW_MENU_SPANCOUNT = 1002;
    private static final int HIDE_MENU_SPANCOUNT = 1003;
    private static final int SHOW_MENU_ORIENTATION = 1004;
    private static final int HIDE_MENU_ORIENTATION = 1005;

    private UltimateProvider mProvider;
    private List<Model> mModelList;
    private DirectionalLayout mLayoutManager;
    private DirectionalLayout mSpanCount;
    private DirectionalLayout mOrientation;
    private Text mTvLayoutManager;
    private Text mTvSpanCount;
    private Text mTvOrientation;
    private Text mTvReverseLayout;
    private DirectionalLayout mMenuLayoutManager;
    private AnimatorProperty mMenuLayoutManagerHideAnimator;
    private AnimatorProperty mMenuLayoutManagerShowAnimator;
    private Text mTvLinear;
    private Text mTvGrid;
    private DirectionalLayout mMenuSpanCount;
    private AnimatorProperty mMenuSpanCountHideAnimator;
    private AnimatorProperty mMenuSpanCountShowAnimator;
    private Text mTvTwo;
    private Text mTvThree;
    private Text mTvFour;
    private Text mTvFive;
    private Text mTvSix;
    private DirectionalLayout mMenuOrientation;
    private AnimatorProperty mMenuOrientationHideAnimator;
    private AnimatorProperty mMenuOrientationShowAnimator;
    private Text mTvVertical;
    private Text mTvHorizontal;
    private Button mConfigUpdate;
    private Button mConfigReset;
    private int mLayoutManagerValue = LAYOUTMANAGER_LINEAR;
    private int mSpanCountValue = 2;
    private int mOrientationValue = Component.VERTICAL;
    private Component mBgCloseMenu;

    private MyEventHandler mHandler = new MyEventHandler(EventRunner.getMainEventRunner());

    @Override
    public void onStart(Intent intent) {
        super.onStart(intent);
    }

    @Override
    public void initData() {
        mModelList = getModels();
        mProvider = new UltimateProvider<Model>(mModelList, getContext());
        mListContainer.setItemProvider(mProvider);
        setTvMenuFeatureText(FEATURE_BASIC);
        setTvMenuConfigVisible();
        Component configComponent = LayoutScatter.getInstance(getContext()).parse(
                ResourceTable.Layout_bottom_sheet_basic_config, null, false);
        mMenuConfig.addComponent(configComponent);
        mLayoutManager = (DirectionalLayout) findComponentById(ResourceTable.Id_layout_manager);
        mMenuLayoutManager = (DirectionalLayout) findComponentById(ResourceTable.Id_menu_layoutmanager);
        mTvLinear = (Text) findComponentById(ResourceTable.Id_tv_linear);
        mTvGrid = (Text) findComponentById(ResourceTable.Id_tv_grid);
        mTvLayoutManager = (Text) findComponentById(ResourceTable.Id_tv_layout_manager);
        mSpanCount = (DirectionalLayout) findComponentById(ResourceTable.Id_span_count);
        mMenuSpanCount = (DirectionalLayout) findComponentById(ResourceTable.Id_menu_span_count);
        mTvTwo = (Text) findComponentById(ResourceTable.Id_tv_two);
        mTvThree = (Text) findComponentById(ResourceTable.Id_tv_three);
        mTvFour = (Text) findComponentById(ResourceTable.Id_tv_four);
        mTvFive = (Text) findComponentById(ResourceTable.Id_tv_five);
        mTvSix = (Text) findComponentById(ResourceTable.Id_tv_six);
        mTvSpanCount = (Text) findComponentById(ResourceTable.Id_tv_span_count);
        mOrientation = (DirectionalLayout) findComponentById(ResourceTable.Id_orientation);
        mMenuOrientation = (DirectionalLayout) findComponentById(ResourceTable.Id_menu_orientation);
        mTvVertical = (Text) findComponentById(ResourceTable.Id_tv_vertical);
        mTvHorizontal = (Text) findComponentById(ResourceTable.Id_tv_horizontal);
        mTvOrientation = (Text) findComponentById(ResourceTable.Id_tv_orientation);
        mTvReverseLayout = (Text) findComponentById(ResourceTable.Id_tv_reverse_layout);
        mConfigUpdate = (Button) findComponentById(ResourceTable.Id_bt_update);
        mConfigReset = (Button) findComponentById(ResourceTable.Id_bt_reset);
        mBgCloseMenu = findComponentById(ResourceTable.Id_bg_closemenu);
        initBgCloseMenuListener();
        initConfig();
        initListener();
        initAnimator();
    }

    private void initBgCloseMenuListener() {
        mBgCloseMenu.setTouchEventListener((component, touchEvent) -> {
            if (mMenuLayoutManager.getVisibility() != Component.HIDE) {
                if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
                    setMenuLayoutManagerVisible(false);
                }
                return true;
            }
            if (mMenuSpanCount.getVisibility() != Component.HIDE) {
                if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
                    setMenuSpanCountVisible(false);
                }
                return true;
            }
            if (mMenuOrientation.getVisibility() != Component.HIDE) {
                if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_UP) {
                    setMenuOrientationVisible(false);
                }
                return true;
            }
            return false;
        });
    }

    private void initListener() {
        mLayoutManager.setClickedListener(component -> {
            setMenuLayoutManagerVisible(true);
        });
        mTvLinear.setClickedListener(component -> {
            mTvLayoutManager.setText(LINEAR);
            mLayoutManagerValue = LAYOUTMANAGER_LINEAR;
        });
        mTvGrid.setClickedListener(component -> {
            mTvLayoutManager.setText(GRID);
            mLayoutManagerValue = LAYOUTMANAGER_GRID;
        });
        mSpanCount.setClickedListener(component -> {
            setMenuSpanCountVisible(true);
        });
        mTvTwo.setClickedListener(component -> {
            mTvSpanCount.setText("Two");
            mSpanCountValue = 2;
        });
        mTvThree.setClickedListener(component -> {
            mTvSpanCount.setText("Three");
            mSpanCountValue = 3;
        });
        mTvFour.setClickedListener(component -> {
            mTvSpanCount.setText("Four");
            mSpanCountValue = 4;
        });
        mTvFive.setClickedListener(component -> {
            mTvSpanCount.setText("Five");
            mSpanCountValue = 5;
        });
        mTvSix.setClickedListener(component -> {
            mTvSpanCount.setText("Six");
            mSpanCountValue = 6;
        });
        mOrientation.setClickedListener(component -> {
            setMenuOrientationVisible(true);
        });
        mTvVertical.setClickedListener(component -> {
            mTvOrientation.setText(VERTICAL);
            mOrientationValue = Component.VERTICAL;
        });
        mTvHorizontal.setClickedListener(component -> {
            mTvOrientation.setText(HORIZONTAL);
            mOrientationValue = Component.HORIZONTAL;
        });
        mConfigUpdate.setClickedListener(this::onClick);
        mConfigReset.setClickedListener(this::onClick);
    }

    private void initAnimator() {
        mMenuLayoutManagerHideAnimator = mMenuLayoutManager.createAnimatorProperty();
        mMenuLayoutManagerHideAnimator.alpha(0).setDuration(ANIMATOR_DURATION);
        mMenuLayoutManagerShowAnimator = mMenuLayoutManager.createAnimatorProperty();
        mMenuLayoutManagerShowAnimator
                .scaleXFrom(0).scaleX(1)
                .scaleYFrom(0).scaleY(1)
                .alphaFrom(0).alpha(1)
                .setDuration(ANIMATOR_DURATION);

        mMenuSpanCountHideAnimator = mMenuSpanCount.createAnimatorProperty();
        mMenuSpanCountHideAnimator.alpha(0).setDuration(ANIMATOR_DURATION);
        mMenuSpanCountShowAnimator = mMenuSpanCount.createAnimatorProperty();
        mMenuSpanCountShowAnimator
                .scaleXFrom(0).scaleX(1)
                .scaleYFrom(0).scaleY(1)
                .alphaFrom(0).alpha(1)
                .setDuration(ANIMATOR_DURATION);

        mMenuOrientationHideAnimator = mMenuOrientation.createAnimatorProperty();
        mMenuOrientationHideAnimator.alpha(0).setDuration(ANIMATOR_DURATION);
        mMenuOrientationShowAnimator = mMenuOrientation.createAnimatorProperty();
        mMenuOrientationShowAnimator
                .scaleXFrom(0).scaleX(1)
                .scaleYFrom(0).scaleY(1)
                .alphaFrom(0).alpha(1)
                .setDuration(ANIMATOR_DURATION);
    }

    @Override
    public void initConfig() {
        mTvLayoutManager.setText(LINEAR);
        mLayoutManagerValue = LAYOUTMANAGER_LINEAR;
        mTvSpanCount.setText("Two");
        mSpanCountValue = 2;
        mTvOrientation.setText(VERTICAL);
        mOrientationValue = Component.VERTICAL;
        mTvReverseLayout.setText("Normal");
    }

    /**
     * setMenuLayoutManagerVisible
     *
     * @param visible 菜单是否可见
     */
    public void setMenuLayoutManagerVisible(boolean visible) {
        if (visible) {
            mHandler.sendEvent(SHOW_MENU_LAYOUTMANAGER);
            mMenuLayoutManagerShowAnimator.start();
        } else {
            mMenuLayoutManagerHideAnimator.start();
            mHandler.sendEvent(HIDE_MENU_LAYOUTMANAGER, ANIMATOR_DURATION);
        }
    }

    private void setMenuSpanCountVisible(boolean visible) {
        if (visible) {
            mHandler.sendEvent(SHOW_MENU_SPANCOUNT);
            mMenuSpanCountShowAnimator.start();
        } else {
            mMenuSpanCountHideAnimator.start();
            mHandler.sendEvent(HIDE_MENU_SPANCOUNT, ANIMATOR_DURATION);
        }
    }

    private void setMenuOrientationVisible(boolean visible) {
        if (visible) {
            mHandler.sendEvent(SHOW_MENU_ORIENTATION);
            mMenuOrientationShowAnimator.start();
        } else {
            mMenuOrientationHideAnimator.start();
            mHandler.sendEvent(HIDE_MENU_ORIENTATION, ANIMATOR_DURATION);
        }
    }

    private void setViewVisible(Component component, int visible) {
        if (component != null) {
            component.setVisibility(visible);
        }
    }

    @Override
    public void configUpdate() {
        mModelList = getModels();
        mProvider.setModels(mModelList);
        mListContainer.scrollTo(0);
    }

    @Override
    public List<Model> getModels() {
        List<Model> list = new ArrayList<Model>();

        List<NumberItem> items = mDataManager.getNumberItems(1000);
        int size = items.size();
        int numColumns;
        List<NumberItem> tempItems = null;
        BasicItemModel basicItemModel = null;
        if (mOrientationValue == Component.VERTICAL) {
            mListContainer.setOrientation(Component.VERTICAL);
            mListContainer.setMarginsTopAndBottom(0, 0);
            list.add(new DistanceModel());
            list.add(new HintModel(getContext().getString(ResourceTable.String_basic_hint), this::onItemDismissed));
        } else {
            mListContainer.setOrientation(Component.HORIZONTAL);
            mListContainer.setMarginsTopAndBottom(Utils.vp2px(getContext(),
                    getContext().getString(ResourceTable.String_height_titleBar)),
                    Utils.vp2px(getContext(), getContext().getString(ResourceTable.String_height_titleBar)));
        }
        numColumns = mLayoutManagerValue == LAYOUTMANAGER_LINEAR ? 1 : mSpanCountValue;
        for (int i = 0; i < size; i += numColumns) {
            tempItems = new ArrayList<>();
            for (int j = i; j < i + numColumns && j < size; j++) {
                tempItems.add(items.get(j));
            }
            basicItemModel = new BasicItemModel(tempItems, numColumns);
            basicItemModel.setOrientation(mOrientationValue);
            list.add(basicItemModel);
        }

        return list;
    }

    @Override
    public void onActive() {
        super.onActive();
    }

    @Override
    public void onForeground(Intent intent) {
        super.onForeground(intent);
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    protected void onBackPressed() {
        if (mMenuLayoutManager.getVisibility() == Component.VISIBLE) {
            setMenuLayoutManagerVisible(false);
            return;
        }
        if (mMenuSpanCount.getVisibility() == Component.VISIBLE) {
            setMenuSpanCountVisible(false);
            return;
        }
        if (mMenuOrientation.getVisibility() == Component.VISIBLE) {
            setMenuOrientationVisible(false);
            return;
        }
        super.onBackPressed();
    }

    @Override
    public void doItemDismissed(int position) {
        mModelList.remove(position);
        mProvider.setModels(mModelList);
    }

    private class MyEventHandler extends EventHandler {
        private MyEventHandler(EventRunner runner) {
            super(runner);
        }

        @Override
        public void processEvent(InnerEvent event) {
            super.processEvent(event);
            switch (event.eventId) {
                case SHOW_MENU_LAYOUTMANAGER:
                    if (mMenuLayoutManager != null && mBgCloseMenu != null) {
                        mMenuLayoutManager.setVisibility(Component.VISIBLE);
                        mBgCloseMenu.setVisibility(Component.VISIBLE);
                    }
                    setViewVisible(mMenuSpanCount, Component.HIDE);
                    setViewVisible(mMenuOrientation, Component.HIDE);
                    break;
                case HIDE_MENU_LAYOUTMANAGER:
                    if (mMenuLayoutManager != null && mBgCloseMenu != null) {
                        mMenuLayoutManager.setVisibility(Component.HIDE);
                        mBgCloseMenu.setVisibility(Component.HIDE);
                    }
                    break;
                case SHOW_MENU_SPANCOUNT:
                    if (mMenuSpanCount != null && mBgCloseMenu != null) {
                        mMenuSpanCount.setVisibility(Component.VISIBLE);
                        mBgCloseMenu.setVisibility(Component.VISIBLE);
                    }
                    setViewVisible(mMenuLayoutManager, Component.HIDE);
                    setViewVisible(mMenuOrientation, Component.HIDE);
                    break;
                case HIDE_MENU_SPANCOUNT:
                    if (mMenuSpanCount != null && mBgCloseMenu != null) {
                        mMenuSpanCount.setVisibility(Component.HIDE);
                        mBgCloseMenu.setVisibility(Component.HIDE);
                    }
                    break;
                case SHOW_MENU_ORIENTATION:
                    if (mMenuOrientation != null && mBgCloseMenu != null) {
                        mMenuOrientation.setVisibility(Component.VISIBLE);
                        mBgCloseMenu.setVisibility(Component.VISIBLE);
                    }
                    setViewVisible(mMenuLayoutManager, Component.HIDE);
                    setViewVisible(mMenuSpanCount, Component.HIDE);
                    break;
                case HIDE_MENU_ORIENTATION:
                    if (mMenuOrientation != null && mBgCloseMenu != null) {
                        mMenuOrientation.setVisibility(Component.HIDE);
                        mBgCloseMenu.setVisibility(Component.HIDE);
                    }
                    break;
                default:
                    break;
            }
        }
    }

}
